package com.fowo.api.syncAmazon.core.sync;

import cn.hutool.core.collection.ListUtil;
import com.amazon.spapi.model.reports.CreateReportSpecification;
import com.amazon.spapi.model.reports.Report;
import com.amazon.spapi.model.reports.ReportDocument;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fowo.api.entity.ListingFather;
import com.fowo.api.entity.ShopInfo;
import com.fowo.api.entity.TmpFbaInventory;
import com.fowo.api.entity.Warehouse;
import com.fowo.api.mapper.ListingFatherMapper;
import com.fowo.api.service.impl.ListingFatherServiceImpl;
import com.fowo.api.service.impl.ShopInfoServiceImpl;
import com.fowo.api.service.impl.TmpFbaInventoryServiceImpl;
import com.fowo.api.service.impl.WarehouseServiceImpl;
import com.fowo.api.syncAmazon.core.AbstractAmazonSyncData;
import com.fowo.api.syncAmazon.core.ReportApiType;
import com.fowo.api.syncAmazon.entity.ApiDefine;
import com.fowo.api.syncAmazon.mapper.AmazonTmpMapper;
import com.fowo.api.syncAmazon.util.AmzDateUtils;
import com.fowo.api.syncAmazon.util.GeneralUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @fileName: ManageFBAInventorySync
 * @Description: 代码目的，作用，如何工作
 * @Author: yyf
 * @Date: 2024/2/22 0022 14:34
 */
@Slf4j
@Component
public class ManageFBAInventorySync extends AbstractAmazonSyncData {
    @Resource
    private ListingFatherMapper listingFatherMapper;
    @Resource
    private WarehouseServiceImpl warehouseService;
    @Resource
    private TmpFbaInventoryServiceImpl tmpFbaInventoryService;
    @Resource
    private AmazonTmpMapper amazonTmpMapper;
    @Resource
    private ShopInfoServiceImpl shopInfoServiceImpl;
    @Resource
    private ListingFatherServiceImpl listingFatherService;

    private ApiDefine apiDefine = ApiDefine.builder()
            .apiCode("manage_FBA_Inventory")
            .initdate(1)
            .timeInterval(1)
            .timeIntervalType("day").build();

    @Override
    protected ApiDefine setApiDefine() {
        return apiDefine;
    }

    @Override
    protected void requestData() throws Exception {
        // 获取卖家账号信息
        String platform = "Amazon";
        this.getAuthority(platform);
        // 查询该账号下所有店铺
        LambdaQueryWrapper<ShopInfo> shopInfosWrapper = new LambdaQueryWrapper<>();
        shopInfosWrapper.eq(ShopInfo::getPlatform,"Amazon")
                .eq(ShopInfo::getSellerAuthStatus,"SQ01");
        List<ShopInfo> shopInfoList = shopInfoServiceImpl.list(shopInfosWrapper);

        // 清空缓存表
        amazonTmpMapper.deleteFbaInventory();

        //请求报告
        for (ShopInfo shopInfo : shopInfoList) {
            //创建报告 -查询参数
            List<String> marketplaceIds = Arrays.asList(shopInfo.getMarketplaceId().split(","));
            CreateReportSpecification body = new CreateReportSpecification();
            body.setReportType(ReportApiType.GET_FBA_MYI_UNSUPPRESSED_INVENTORY_DATA);
            body.setMarketplaceIds(marketplaceIds);
            // 获取拉取的时间区间
            body.setDataStartTime(AmzDateUtils.getOffsetDateTimeUTC(startTime));
            body.setDataEndTime(AmzDateUtils.getOffsetDateTimeUTC(endTime));


            // 第一步 创建报告
            final String reportId = retryCreateReport(shopInfo, body);
            // 第二步 检验报告是否完成
            Report report = retryCheckReport(shopInfo, reportId);
            // 第三步 获取报告连接
            ReportDocument reportDocument = getReportDocument(shopInfo,report.getReportDocumentId());
            log.info(reportDocument.getUrl());

            if (reportDocument != null) {
                String compressionAlgorithm = reportDocument.getCompressionAlgorithm() != null ? reportDocument.getCompressionAlgorithm().getValue() : null;
                BufferedReader reader = this.getAndUnzipReport(reportDocument.getUrl(), compressionAlgorithm);
                try {
                    download(reader, shopInfo);
                }catch (Exception ex){
                    log.error("缓存至临时表异常："+ex);
                }finally {
                    reader.close();
                }
            }
        }
    }

    @Override
    protected <T> void download(T param, ShopInfo shop) throws IOException, IllegalArgumentException {
        BufferedReader reader = null;
        if (param instanceof BufferedReader){
            try {
                reader = (BufferedReader)param;
            }catch (Exception e){
                throw new RuntimeException(e);
            }
        }

        int lineNumber = 0;
        String line = null;
        Map<String,Integer> titleList = new HashMap<>();
        List<TmpFbaInventory> list = new ArrayList<>();

        List<ListingFather> listingFathers = listingFatherMapper.selectList(Wrappers.lambdaQuery(ListingFather.class)
                .eq(ListingFather::getShop, shop.getId()));
        Warehouse warehouse = warehouseService.getOne(Wrappers.lambdaQuery(Warehouse.class)
                .eq(Warehouse::getSid, shop.getId()));
        Long wid = warehouse.getId() != null ? warehouse.getId() : null;

        while ((line = reader.readLine()) != null) {
            String[] info = line.split("\t");
            int length = info.length;
            if (lineNumber == 0) {
                for (int i = 0; i < length; i++) {
                    titleList.put(info[i],i);
                }
            } else {

                Map<String, Object> fields = this.getFieldsFromInfo(info, titleList);
                TmpFbaInventory tmp = new TmpFbaInventory();
                String asin = fields.get("asin").toString();
                String sku = fields.get("sku").toString();
                String mfnListingExits = fields.get("mfn-listing-exists").toString();
                String afnListingExits = fields.get("afn-listing-exists").toString();

                if(mfnListingExits.equals("Yes")){
                    tmp.setFulfillmentChannelType("FBM");
                }else if(afnListingExits.equals("Yes")){
                    tmp.setFulfillmentChannelType("FBA");
                }

                final ListingFather listingFather = listingFathers.stream()
                        .filter(l -> l.getShop().equals(shop.getId()) && l.getAsin().equals(asin) && l.getMsku().equals(sku))
                        .findAny()
                        .orElse(new ListingFather());
                tmp.setPicture(listingFather.getImg());
                tmp.setListingId(listingFather.getId());
                tmp.setProductId(listingFather.getPairProduct());
                tmp.setSku(listingFather.getSku());
                tmp.setHead(listingFather.getPrincipal());

                tmp.setCreateTime(new Date());
                tmp.setLastUpdateTime(new Date());
                tmp.setWarehouse(wid);
                tmp.setSid(shop.getId());
                tmp.setAsin(asin);
                tmp.setMsku(sku);
                tmp.setFnsku((String)fields.get("fnsku"));
                tmp.setFbaAvailableForSale(GeneralUtil.getIntegerValue(fields.get("afn-fulfillable-quantity")));
                tmp.setFbmAvailableForSale(GeneralUtil.getIntegerValue(fields.get("mfn-fulfillable-quantity")));
                tmp.setWarehouseToBeAdjusted(0);
                tmp.setDuringWarehouseAdjustment(0);
                tmp.setToBeShipped(0);
                tmp.setPlannedWarehousing(GeneralUtil.getIntegerValue(fields.get("afn-inbound-working-quantity")));
                tmp.setStandardInTransit(GeneralUtil.getIntegerValue(fields.get("afn-inbound-shipped-quantity")));
                tmp.setActualInTransit(0);
                tmp.setInStorage(GeneralUtil.getIntegerValue(fields.get("afn-inbound-receiving-quantity")));
                tmp.setNotAvailableForSale(GeneralUtil.getIntegerValue(fields.get("afn-unsellable-quantity")));
                tmp.setUnderInvestigation(GeneralUtil.getIntegerValue(fields.get("afn-researching-quantity")));
                tmp.setWarningStatus("");

                fields.get("product-name");
                fields.get("condition");
                fields.get("your-price");
                fields.get("afn-warehouse-quantity");
                fields.get("afn-reserved-quantity");
                fields.get("afn-total-quantity");
                fields.get("per-unit-volume");
                fields.get("afn-reserved-future-supply");
                fields.get("afn-future-supply-buyable");

                list.add(tmp);
            }
            lineNumber++;
            // Process line by line.
        }
        // 与listingFather做关联
        getDetailFromListingFather(list,shop);

        // 写入同步数据量
        Integer dataVolume = apiRequestLog.getDataVolume() == null ? 0 : apiRequestLog.getDataVolume();
        apiRequestLog.setDataVolume(dataVolume+list.size());

        tmpFbaInventoryService.saveBatch(list);
    }

    @Override
    protected void updateOrInsertData() {
        amazonTmpMapper.insertFbaInventory();
        amazonTmpMapper.updateFbaInventory();

        // 完成本次同步日志
        apiDefine.setStatus(ApiDefine.SUCCESS);
        if(apiDefine.getLastDataTime() == null){
            apiDefine.setLastDataTime(endTime);
        } else if (endTime.after(apiDefine.getLastDataTime())) {
            apiDefine.setLastDataTime(endTime);
        }
        apiDefineService.getBaseMapper().updateById(apiDefine);
    }

    private void getDetailFromListingFather(List<TmpFbaInventory> lists,ShopInfo shopInfo){
        if(lists == null || lists.size() == 0){
            return;
        }
        List<ListingFather> listingFather = new ArrayList<>();
        for (List<TmpFbaInventory> tmpSellOrderDetails : ListUtil.partition(lists, 500)) {
            List<String> mskus = tmpSellOrderDetails.stream().map(TmpFbaInventory::getMsku).collect(Collectors.toList());
            List<ListingFather> tmp = listingFatherService.list(Wrappers.lambdaQuery(ListingFather.class).eq(ListingFather::getShop, shopInfo.getId())
                    .in(ListingFather::getMsku, mskus));
            listingFather.addAll(tmp);
        }

        for (TmpFbaInventory list : lists) {
            List<ListingFather> collect = listingFather.stream().filter(r -> r.getMsku().equals(list.getMsku())).collect(Collectors.toList());
            if (collect != null && collect.size() > 0){
                Optional<ListingFather> exist1 = collect.stream().filter(r -> r.getStatus().equals("1")).findFirst();
                Optional<ListingFather> exist2 = collect.stream().filter(r -> r.getStatus().equals("0")).findFirst();
                if (exist1.isPresent()){
                    list.setListingId(exist1.get().getId());
                }else if(exist2.isPresent()){
                    list.setListingId(exist2.get().getId());
                }else{
                    list.setListingId(collect.get(0).getId());
                }
            }
        }
    }
}
